/**
 * @FileName: PinyinTextServiceImpl.java
 * @Package: service.impl
 * @author youshipeng
 * @created 2016/10/27 20:19
 * <p>
 * Copyright 2016 ziroom
 */
package top.swimmer.boot.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.swimmer.boot.annotation.ApplicationService;
import top.swimmer.boot.dao.PinyinWordMapper;
import top.swimmer.boot.dao.WordClickMapper;
import top.swimmer.boot.model.PinyinWord;
import top.swimmer.boot.model.options.PinyinWordAnalyzeSearchOptions;
import top.swimmer.boot.model.options.PinyinWordSearchOptions;
import top.swimmer.boot.model.value.WordClickCount;
import top.swimmer.boot.service.PinyinWordService;
import top.swimmer.boot.util.ChineseUtils;
import top.swimmer.boot.util.enums.LexemeType;
import top.swimmer.boot.util.model.ChineseSentence;
import top.swimmer.boot.util.model.Lexeme;
import top.swimmer.tools.collection.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

import static top.swimmer.boot.util.PinyinUtils.convertSmartAll;

/**
 * <p></p>
 *
 * <PRE>
 * <BR>	修改记录
 * <BR>-----------------------------------------------
 * <BR>	修改日期			修改人			修改内容
 * </PRE>
 *
 * @author youshipeng
 * @since 1.0
 * @version 1.0
 */
@ApplicationService(value = "pinyinWordService")
public class PinyinWordServiceImpl extends BaseServiceImpl<PinyinWord, PinyinWordMapper> implements PinyinWordService {

    @Autowired
    WordClickMapper wordClickMapper;

    @Override
    public List<WordClickCount> searchByClickCount(PinyinWordAnalyzeSearchOptions options) {
        return mapper.searchByClickCount(options);
    }

    @Override
    public List<PinyinWord> search(PinyinWordSearchOptions options) {
        return mapper.search(options);
    }

    @Override
    public List<List<WordClickCount>> analyzeSearch(String input) throws Exception {
        ChineseSentence sentence = ChineseUtils.encapsulation(input);
        List<List<WordClickCount>> results = new ArrayList<>();
        SentenceAnalyzeResult sentenceAnalyzeResult = new SentenceAnalyzeResult(sentence, new ArrayList<WordClickCount>());
        do {
            sentenceAnalyzeResult = analyzeBest(sentenceAnalyzeResult.getLastSentence());
            if (!CollectionUtils.isEmpty(sentenceAnalyzeResult.getResults())) {
                results.add(sentenceAnalyzeResult.getResults());
            }
        } while (!CollectionUtils.isEmpty(sentenceAnalyzeResult.getLastSentence().getSentenceUnits()));
        return results;
    }

    private SentenceAnalyzeResult analyzeBest(ChineseSentence sentence) throws Exception {
        StringBuilder wholeSearch = new StringBuilder(""); //用于全拼搜索
        StringBuilder chineseSearch = new StringBuilder(""); //用于中文搜索
        StringBuilder acronymSearch = new StringBuilder(""); //用于缩写搜索
        StringBuilder chineseFilter = new StringBuilder("%"); //用于中文模糊匹配
        StringBuilder pinyinFilter = new StringBuilder("%"); //用于拼音模糊匹配
        SentenceAnalyzeResult result = null; //返回的结果
        LexemeType currentLexemeType; //当前词元类型
        LexemeType lastLexemeType = null; //之前词元最低级
        List<Lexeme> lexemes = sentence.getSentenceUnits(); //累积词元最低级
        for (int i = 0; i < lexemes.size(); i++) {
            Lexeme lexeme = lexemes.get(i);
            currentLexemeType = lexeme.getLexemeType();

            String content = lexeme.getContent();
            switch (currentLexemeType) {
                case CHINESE:
                    String pinyin = convertSmartAll(content);
                    chineseSearch.append(content);
                    wholeSearch.append(pinyin);
                    acronymSearch.append(pinyin.charAt(0));
                    chineseFilter.append(content).append("%");
                    break;
                case WHOLE:
                    wholeSearch.append(content);
                    acronymSearch.append(content.charAt(0));
                    pinyinFilter.append(content).append("%");
                    break;
                case ACRONYM:
                    acronymSearch.append(content);
                    break;
            }
            lastLexemeType = LexemeType.changeDown(lastLexemeType, currentLexemeType);
            PinyinWordAnalyzeSearchOptions options = new PinyinWordAnalyzeSearchOptions(
                    chineseSearch.toString(), wholeSearch.toString(), acronymSearch.toString(),
                    chineseFilter.toString(), pinyinFilter.toString(), lastLexemeType
            );
            List<WordClickCount> wordClickCounts = mapper.searchByClickCount(options);
            if (!CollectionUtils.isEmpty(wordClickCounts)) {
                ChineseSentence lastSentence = new ChineseSentence();
                lastSentence.setSentenceUnits(lexemes.subList(i + 1, lexemes.size()));
                result = new SentenceAnalyzeResult(lastSentence, wordClickCounts);
            } else if (i == 0) {
                ChineseSentence lastSentence = new ChineseSentence();
                lastSentence.setSentenceUnits(lexemes.subList(i + 1, lexemes.size()));
                result = new SentenceAnalyzeResult(lastSentence, wordClickCounts);
                return result;
            } else {
                if (!CollectionUtils.isEmpty(result.getResults())) {
                    final List<WordClickCount> clickCounts = result.getResults();
                    final int index = i;
                    result.setResults(new ArrayList<WordClickCount>(){{
                        for (WordClickCount clickCount : clickCounts) {
                            if (clickCount.getWord().length() <= index) {
                                add(clickCount);
                            }
                        }
                    }});
                }
                return result;
            }
        }
        return result;
    }

    private class SentenceAnalyzeResult {
        private ChineseSentence lastSentence;
        private List<WordClickCount> results;

        private SentenceAnalyzeResult(ChineseSentence lastSentence, List<WordClickCount> results) {
            this.lastSentence = lastSentence;
            this.results = results;
        }

        private ChineseSentence getLastSentence() {
            return lastSentence;
        }

        private void setLastSentence(ChineseSentence lastSentence) {
            this.lastSentence = lastSentence;
        }

        private List<WordClickCount> getResults() {
            return results;
        }

        private void setResults(List<WordClickCount> results) {
            this.results = results;
        }
    }
}